(function () {
	// region 常量
	// 键码
	var KeyCode = {
		Backspace : 8,
		Tab : 9,
		Enter : 13,
		Shift : 16,
		Ctrl : 17,
		Alt : 18,
		PauseBreak : 19,
		CapsLock : 20,
		Esc : 27,
		PageUp : 33,
		PageDown : 34,
		End : 35,
		Home : 36,
		LeftArrow : 37,
		UpArrow : 38,
		RigthArrow : 39,
		DownArrow : 40,
		Ins : 45,
		Del : 46,
		Num0 : 48,
		Num1 : 49,
		Num2 : 50,
		Num3 : 51,
		Num4 : 52,
		Num5 : 53,
		Num6 : 54,
		Num7 : 55,
		Num8 : 56,
		Num9 : 57,
		A : 65,
		B : 66,
		C : 67,
		D : 68,
		E : 69,
		F : 70,
		G : 71,
		H : 72,
		I : 73,
		J : 74,
		K : 75,
		L : 76,
		M : 77,
		N : 78,
		O : 79,
		P : 80,
		Q : 81,
		R : 82,
		S : 83,
		T : 84,
		U : 85,
		V : 86,
		W : 87,
		X : 88,
		Y : 89,
		Z : 90,
		WindowsLeft : 91,
		WindowsRight : 92,
		ContextMenu : 93,
		Numpad0 : 96,
		Numpad1 : 97,
		Numpad2 : 98,
		Numpad3 : 99,
		Numpad4 : 100,
		Numpad5 : 101,
		Numpad6 : 102,
		Numpad7 : 103,
		Numpad8 : 104,
		Numpad9 : 105,
		NumpadAsterisk : 106,
		NumpadAdd : 107,
		NumpadSub : 109,
		NumpadDot : 110,
		NumpadSlash : 111,
		F0 : 111,
		F1 : 112,
		F2 : 113,
		F3 : 114,
		F4 : 115,
		F5 : 116,
		F6 : 117,
		F7 : 118,
		F8 : 119,
		F9 : 120,
		F10 : 121,
		F11 : 122,
		F12 : 123,
		NumLock : 144,
		ScrollLock : 145,
		Semicolon : 186,
		Comma : 188,
		Sub : 189,
		Dot : 190,
		Slash : 191,
		GraveAccent : 192,
		Equal : 61,
		LeftBracket : 219,
		Backslash : 220,
		RigthBracket : 221,
		Quote : 222
	};
	// endregion

	// region util
	function empty() {
	}

	// 遍历对象
	function loopObj( obj, block ) {
		for ( var key in obj ) {
			block( key, obj[key] );
		}
	}

	// 将一个对象插入到另一个对象
	function insert( obj1, obj2 ) {
		loopObj( obj2, function ( key, value ) {
			obj1[key] = value;
		} );
	}

	// 遍历数组
	function loopArray( list, block ) {
		var i, len;
		for ( i = 0, len = list.length; i < len; i++ ) {
			block( list[i], i );
		}
	}

	// 自动属性
	function AutoAttribute( setter ) {
		var val = null;
		setter = setter || empty;
		return function ( value ) {
			if ( value !== undefined ) {
				var oldVal = val;
				val = value;
				setter( val, oldVal );
			}
			else {
				return val;
			}
		};
	}

	// 根据字典调用指令
	function call( inst, obj ) {
		loopObj( obj, function ( key, value ) {
			inst[key]( value );
		} );
	}

	// 设置HTML元素样式
	function setStyle( el, styleName, styleValue ) {
		el.style.setProperty( styleName, styleValue, "" );
	}

	// 创建HTML元素
	function createElement( tagName ) {
		var el = document.createElement( tagName );
		setStyle( el, "position", "absolute" );
		setStyle( el, "display", "block" );
		return el;
	}

	// 生成HTML元素的样式setter
	function StyleSetter( styleName ) {
		switch ( styleName ) {
			case "height" :
			case "width" :
			case "left" :
			case "top" :
				return function ( el, styleValue ) {
					el.style.setProperty( styleName, ( typeof styleValue === "number" ) ? styleValue + "px" : styleValue, "" );
				};
			case "z-index" :
			case "opacity" :
				return function ( el, styleValue ) {
					el.style.setProperty( styleName, styleValue + "", "" );
				};
			default :
				return function ( el, styleValue ) {
					el.style.setProperty( styleName, ( typeof styleValue === "number" ) ? styleValue + "px" : styleValue, "" );
				};
		}
	}

	// 计算一个元素到对于文档的偏移量,函数的函数模板
	// 加入文档偏移量的原因是为了处理拖动
	function CaculateElementDocumentOffset( offsetName ) {
		return function ( el ) {
			var retVal = 0;

			for ( var cur = el; cur !== null; cur = cur.offsetParent ) {
				retVal += cur[offsetName];
			}

			return retVal;
		};
	}

	var GetElementDocumentLeft = CaculateElementDocumentOffset( "offsetLeft" );
	var GetElementDocumentTop = CaculateElementDocumentOffset( "offsetTop" );
	// endregion

	// region 事件
	// 事件
	function Event( basicTask ) {
		var tail = null;
		basicTask = basicTask || empty;
		return {
			trig : function () {
				var arg = arguments;
				basicTask.apply( null, arg ); // 回调基本事件

				// 遍历注册事件
				var list = [];
				// 取出事件
				for ( var cur = tail; cur !== null; cur = cur.previous ) {
					list.push( cur.value );
				}

				// 遍历事件
				loopArray( list, function ( item ) {
					item.apply( null, arg );
				} );
			},
			regist : function ( task ) {
				var node = {
					value : task,
					next : null,
					previous : tail
				};

				// 插入到尾节点之后,并成为尾节点
				if ( tail !== null ) {
					tail.next = node;
				}
				tail = node;

				return {
					remove : function () {
						// 连接前后
						if ( node.previous !== null ) {
							node.previous.next = node.next;
						}
						if ( node.next !== null ) {
							node.next.previous = node.previous;
						}
						else {
							// node无后,即最后一个节点
							tail = node.previous;
						}

						node = null; // 移除节点
					}
				};
			}
		};
	}

	// 注册事件
	function EventRegist( el, eventName, onEvent ) {
		var event = Event(); // 创建事件
		if ( onEvent !== undefined ) {
			el["on" + eventName] = function ( arg ) {
				var retVal = onEvent( arg );
				if ( retVal || retVal === undefined ) {
					event.trig( arg );
				}
			};
		}
		return function ( task ) {
			var myTask = event.regist( task );
			if ( el["on" + eventName] === null ) {
				el["on" + eventName] = function ( arg ) {
					event.trig( arg );
				};
			}
			return {
				remove : myTask.remove
			};
		};
	}

	// 阻止默认事件
	function preventDefault( event ) {
		event.preventDefault();
	}

	var docOnMousemove = EventRegist( document, "mousemove", preventDefault );
	var docOnMouseup = EventRegist( document, "mouseup", preventDefault );

	// mousedown事件
	function EventMousedown( el ) {
		return EventRegist( el, "mousedown", function ( event ) {
			function EventRegister( eventRegister ) {
				return function ( task ) {
					var mainEvent = eventRegister( task );
					var mouseUpEvent = null;
					mouseUpEvent = docOnMouseup( function () {
						mainEvent.remove();
						mouseUpEvent.remove();
					} );
				};
			}

			event.onMousemove = EventRegister( docOnMousemove );
			event.onMouseup = EventRegister( docOnMouseup );
		} );
	}

	// endregion

	// region 元素
	function setTextContect( el, val ) {
		if ( val === undefined ) {
			return ( typeof el.textContent === "string" ) ? el.textContent : el.innerText;
		}
		else {
			if ( typeof el.textContent === "string" ) {
				el.textContent = val;
			}
			else {
				el.innerText = val;
			}
		}
	}

	function Element( info ) {
		// 将样式命中的横杠替换为下划线
		function StyleName( styleName ) {
			return styleName.replace( /-/g, function () {
				return "_";
			} );
		}

		// 事件注册方法由click变为onClick
		function EventName( eventName ) {
			return "on" + eventName.replace( /./, function ( ch ) {
				return ch.toUpperCase();
			} );
		}

		// 指令集生成器
		function genInsts( pack, nameList, attributeGenner, nameGenner ) {
			loopArray( nameList, function ( name ) {
				pack[nameGenner === undefined ? name : nameGenner( name )] = attributeGenner( name );
			} );
		}

		return function ( area, attr ) {
			var el = createElement( info.tagName ); // 创建元素

			// left,top,zIndex,opacity
			function Attr( styleName ) {
				return AutoAttribute( function ( val ) {
					StyleSetter( styleName )( el, val );
				} );
			}

			// 样式设置器
			function StyleSetterA( styleName ) {
				return function ( val ) {
					StyleSetter( styleName )( el, val );
				};
			}

			// 属性属性
			function AttrAttribute( attrName ) {
				switch ( attrName ) {
					case "text" :
						return function ( val ) {
							setTextContect( el, val );
						};
					case "html" :
						return function ( val ) {
							if ( val === undefined ) {
								return el.innerHTML;
							}
							else {
								el.innerHTML = val;
							}
						};
					case "value" :
						return function ( val ) {
							if ( val === undefined ) {
								return el.value;
							}
							else {
								el.value = val;
							}
						};
					case "attr":
						return function ( flag ) {
							if ( flag ) {
								el.setAttribute( "disabled", "disabled" );
							}
							else {
								el.removeAttribute( "disabled" );
							}
						};
					default :
						return function ( val ) {
							if ( val === undefined ) {
								return el.getAttribute( attrName );
							}
							else {
								el.setAttribute( attrName, val );
							}
						};
				}
			}

			// 属性指令
			var attrInst = {
				cursor : StyleSetterA( "cursor" ),
				opacity : Attr( "opacity" ),
				left : Attr( "left" ),
				top : Attr( "top" ),
				zIndex : Attr( "z-index" ),
				visible : function ( val ) {
					setStyle( el, "display", val ? "block" : "none" );
				},
				onMousedown : EventMousedown( el )
			};

			genInsts( attrInst, info.style, StyleSetterA, StyleName ); // 样式指令集
			genInsts( attrInst, info.attr, AttrAttribute ); // 属性指令集
			genInsts( attrInst, info.event, function ( eventName ) {
				return EventRegist( el, eventName );
			}, EventName ); // 事件指令集

			info.hack( el, attrInst, StyleSetterA ); // 回调hack

			call( attrInst, attr || {} ); // 设置属性

			insert( attrInst, {
				remove : function () {
					el.parentNode.removeChild( el );
					el = null;
				},
				offsetWidth : function () {
					return el.offsetWidth;
				},
				offsetHeight : function () {
					return el.offsetHeight;
				},
				documentLeft : GetElementDocumentLeft( el ),
				documentTop : GetElementDocumentTop( el )
			} ); // 插入非属性指令

			area.lay( el ); // 加载到body上

			return attrInst;
		};
	}

	var comboStyle = {
		border : ["border", "border-style", "border-width", "border-color", "border-image", "border-radius", "box-shadow", "border-top", "border-bottom",
			"border-left", "border-right", "border-top-right-radius", "border-bottom-right-radius", "border-bottom-left-radius", "border-top-left-radius",
			"border-top-color", "border-right-color", "border-left-color", "border-bottom-color", "border-top-style", "border-right-style",
			"border-left-style", "border-bottom-style", "border-top-width", "border-right-width", "border-left-width", "border-bottom-width"],
		font : ["font", "font-family", "font-size", "font-style", "font-weight", "color", "text-decoration", "text-shadow", "letter-spacing", "text-overflow",
			"white-space", "line-height", "word-spacing"],
		background : ["background", "background-clip", "background-size", "background-box", "background-color", "background-image", "background-position",
			"background-repeat", "background-attachment"],
		padding : ["padding", "padding-left", "padding-right", "padding-top", "padding-bottom"]
	};

	var comboEvent = {
		mouse : ["mouseup", "mousemove", "mouseover", "mouseout", "click", "dblclick"],
		key : ["blur", "focus", "input", "keypress", "keyup"]
	};

	// 连接两个数组,返回结果
	function concat( arr1, arr2 ) {
		return arr1.concat( arr2 );
	}

	// 查找字典生成数组
	function genArrayByDict( arr, dict ) {
		var retVal = [];
		loopArray( arr, function ( val ) {
			retVal = concat( retVal, dict[val] );
		} );
		return retVal;
	}

	// 生成元素信息
	function El( tagName, info ) {
		return Element( {
			tagName : tagName,
			hack : info.hack || empty,
			style : concat( info.style || [], genArrayByDict( info.comboStyle || [], comboStyle ) ),
			event : concat( genArrayByDict( info.event || [], comboEvent ), comboEvent.mouse ),
			attr : info.attr || []
		} );
	}

	function LineEl( sizeName, posName ) {
		return El( "div", {
			event : ["mouse"],
			hack : function ( el, insts, StyleSetter ) {
				setStyle( el, "border-" + posName + "-style", "solid" );

				// 添加指令
				insert( insts, {
					length : StyleSetter( sizeName ),
					width : StyleSetter( "border-" + posName + "-width" ),
					color : StyleSetter( "border-" + posName + "-color" ),
					style : StyleSetter( "border-" + posName + "-style" )
				} );
			}
		} );
	}

	function InputEL( type, attr ) {
		return El( "input", {
			attr : concat( ["disabled", "value", "name"], attr || [] ),
			style : ["width", "height"],
			comboStyle : ["border", "font", "background", "padding"],
			event : ["key"],
			hack : function ( el ) {
				el.type = type;
			}
		} );
	}

	var element = {
		Button : El( "button", {
			attr : ["text", "title", "disabled"],
			style : ["height", "width"],
			comboStyle : ["border", "font", "background"]
		} ),
		Label : El( "div", {
			attr : ["disabled", "text", "html", "title"],
			style : ["width", "text-align"],
			comboStyle : ["border", "font", "background", "padding"],
			hack : function ( el, insts ) {
				el.addEventListener( "mousedown", function ( event ) {
					event.preventDefault(); // 阻止选中事件
				}, false );
				setStyle( el, "overflow", "hidden" );
				setStyle( el, "white-space", "nowrap" );
				insts.cursor( "default" );
			}
		} ),
		Anchor : El( "a", {
			attr : ["disabled", "text", "href", "title"],
			style : ["width", "height"],
			comboStyle : ["border", "font", "background", "padding"],
			hack : function ( el ) {
				el.href = "javascript:void(0)";
			}
		} ),
		Box : El( "div", {
			attr : ["html", "title"],
			style : ["height", "width"],
			comboStyle : ["border", "background"]
		} ),
		VLine : LineEl( "height", "left" ),
		HLine : LineEl( "width", "top" ),
		Image : El( "img", {
			attr : ["src", "title"],
			style : ["height", "width"]
		} ),
		TextBox : InputEL( "text", ["readonly", "maxlength"] ),
		PasswordBox : InputEL( "password", ["readonly", "maxlength"] ),
		Select : El( "select", {
			attr : ["disabled", "value", "multiple"],
			hack : function ( parent, insts ) {
				insert( insts, {
					items : function ( items ) {
						loopArray( items, function ( item ) {
							var el = createElement( "option" );
							el.setAttribute( "value", item.value );
							setTextContect( el, item.text );
							parent.appendChild( el );
						} );
					} } );
			}
		} )
	};
	// endregion 容器

	// region 布局
	// 区域
	function Area( container, attr ) {
		var div = createElement( "div" );
		setStyle( div, "overflow", "hidden" ); // 默认是hidden,超出部分截断

		function Attr( styleName ) {
			return AutoAttribute( function ( val ) {
				StyleSetter( styleName )( div, val );
			} );
		}

		function ScrollAttribute( scrollName ) {
			return function ( val ) {
				if ( val === undefined ) {
					return div[scrollName];
				}
				else {
					div[scrollName] = val;
				}
			};
		}

		// 指令集
		var insts = {
			left : Attr( "left" ),
			top : Attr( "top" ),
			zIndex : Attr( "z-index" ),
			opacity : Attr( "opacity" ),
			width : function ( val ) {
				StyleSetter( "width" )( div, val );
			},
			height : function ( val ) {
				StyleSetter( "height" )( div, val );
			},
			background_color : function ( val ) {
				setStyle( div, "background-color", val );
			},
			cursor : function ( val ) {
				setStyle( div, "cursor", val );
			},
			scrollHeight : function () {
				return div.scrollHeight;
			},
			scrollWidth : function () {
				return div.scrollWidth;
			},
			overflowX : function ( val ) {
				setStyle( div, "overflow-x", val );
			},
			overflowY : function ( val ) {
				setStyle( div, "overflow-y", val );
			},
			scrollLeft : ScrollAttribute( "scrollLeft" ),
			scrollTop : ScrollAttribute( "scrollTop" ),
			onClick : EventRegist( div, "click" ),
			onDblclick : EventRegist( div, "dblclick" ),
			onMousedown : EventMousedown( div ),
			onMouseup : EventRegist( div, "mouseup" ),
			onMousemove : EventRegist( div, "mousemove" ),
			onMouseover : EventRegist( div, "mouseover" ),
			onMouseout : EventRegist( div, "mouseout" ),
			visible : function ( val ) {
				setStyle( div, "display", val ? "block" : "none" );
			}
		};

		call( insts, attr || {} ); // 调用指令集

		insert( insts, {
			remove : function () {
				container.removeChild( div );
				div = null;
			},
			area : function ( posSize ) {
				return Area( div, posSize );
			},
			lay : function ( el ) {
				div.appendChild( el );
			},
			offsetWidth : function () {
				return div.offsetWidth;
			},
			offsetHeight : function () {
				return div.offsetHeight;
			},
			documentLeft : GetElementDocumentLeft( div ),
			documentTop : GetElementDocumentTop( div )
		} );

		container.appendChild( div ); // 加载到屏幕上
		return insts;
	}

	// endregion

	// region 其他功能
	// 定时器
	function Timer( task, interval ) {
		var timeout = null; // timeout句柄

		// 清除timeout句柄
		function removeTimeout() {
			if ( timeout !== null ) {
				window.clearTimeout( timeout );
			}
			timeout = null;
		}

		return {
			start : function () {
				removeTimeout();
				timeout = window.setTimeout( function () {
					timeout = window.setTimeout( arguments.callee, interval );
					task();
				}, interval );
			},
			stop : removeTimeout,
			interval : function ( val ) {
				if ( val === undefined ) {
					interval = val;
				}
				else {
					return interval;
				}
			}
		};
	}

	// endregion

	// region onload
	window.Z = {
		KeyCode : KeyCode,
		element : element,
		Event : Event
	};

	window.onLoad = function ( onLoad ) {
		// 初始化
		window.onload = function () {
			var body = document.body;
			var keyStat = new Array( 256 ); // 键盘状态
			for ( var i = 0; i != 256; ++i ) {
				keyStat[i] = false;
			}

			// 设置为绝对定位,并去掉默认的margin
			setStyle( body, "position", "absolute" );
			setStyle( body, "margin", "0px" );

			var bodyArea = Area( body, {
				overflowX : "auto",
				overflowY : "auto"
			} ); // 顶级Area

			var redrawEvent = Event( function redraw( size ) {
				bodyArea.height( size.height );
				bodyArea.width( size.width );
			} ); // 重绘事件

			// 重绘
			function redraw() {
				redrawEvent.trig( {
					width : Math.max( document.documentElement.scrollWidth, document.documentElement.clientWidth ),
					height : Math.max( document.documentElement.scrollHeight, document.documentElement.clientHeight )
				} );
			}

			// 窗口改变大小时,触发重绘事件,进而改变顶级容器的大小
			window.onresize = redraw;

			redraw(); // 重绘

			onLoad( {
				lay : bodyArea.lay,
				area : bodyArea.area,
				onResize : redrawEvent.regist,
				offsetHeight : bodyArea.offsetHeight,
				offsetWidth : bodyArea.offsetWidth,
				overflowX : bodyArea.overflowX,
				overflowY : bodyArea.overflowY,
				cursor : function ( val ) {
					setStyle( document.body, "cursor", val );
				},
				Timer : Timer,
				setTimeout : function ( task, interval ) {
					var timeout = window.setTimeout( task, interval );
					return {
						remove : function () {
							window.clearTimeout( timeout );
						}
					};
				},
				onKeydown : EventRegist( document, "keydown", function ( event ) {
					if ( keyStat[event.keyCode] === false ) {
						keyStat[event.keyCode] = true;
						return true;
					}
					return false;
				} ),
				onKeyup : EventRegist( document, "keyup", function ( event ) {
					keyStat[event.keyCode] = false;
				} )
			} ); // 回调启动函数

			redraw(); // 重绘

			// 释放内存
			window.onload = null;
			delete window.onLoad;
		};
	};
	// endregion
})();